﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Com.PhilChuang.Mobile.Apps.LocationSender.Ui.Views;
using Com.PhilChuang.Pmvp.Model.Services;
using Com.PhilChuang.Pmvp.Ui.Presenters;
using Com.PhilChuang.Pmvp.Utils;
using Com.PhilChuang.Utils;

namespace Com.PhilChuang.Mobile.Apps.LocationSender.Ui.Presenters
{
	public class WelcomePresenter : AbstractLocationSenderAppPresenter<IWelcomeView>
	{
		#region Constants
		private const int ASK_TO_RATE_NUM_INTERVAL = 5; // ask every 5 runs
		private const String ASKED_TO_RATE = "WelcomePresenter.ASKED_TO_RATE";
		#endregion

		#region Private members
		private bool m_AskedToRate = false;
		private readonly ITransientAppStateService m_TransientState;
		#endregion

		#region Constructors / Dispose
		public WelcomePresenter () : this (AppServiceLocator.Instance.GetImpl<IWelcomeView> ())
		{
		}

		public WelcomePresenter (IWelcomeView view) : base (view)
		{
			m_TransientState = AppServiceLocator.Instance.GetImpl<ITransientAppStateService> ();
		}
		#endregion

		#region AbstractPresenter implementation
		/// <summary>
		/// Subscribe to View events after the View is registered during Presenter instantiation.
		/// Call base impl as the first step.
		/// </summary>
		protected override void SubscribeToViewEvents ()
		{
			base.SubscribeToViewEvents ();

			View.DoSelectContacts += OnDoSelectContacts;
			View.DoResend += OnDoResend;
			View.DoOpenAboutView += OnDoOpenAboutView;
			View.DoLaunchAppRateLink += OnDoLaunchAppRateLink;
			View.DoOpenSettingsView += OnDoOpenSettingsView;
		}

		/// <summary>
		/// Unsubscribes to View events after the View has Closed.
		/// Call base impl as the first step.
		/// </summary>
		protected override void UnsubscribeFromViewEvents ()
		{
			base.UnsubscribeFromViewEvents ();

			View.DoSelectContacts -= OnDoSelectContacts;
			View.DoResend -= OnDoResend;
			View.DoOpenAboutView -= OnDoOpenAboutView;
			View.DoLaunchAppRateLink -= OnDoLaunchAppRateLink;
			View.DoOpenSettingsView -= OnDoOpenSettingsView;
		}

		/// <summary>
		/// Updates the View with Presenter data.
		/// Call base impl as the last step.
		/// </summary>
		protected override void UpdateToView ()
		{
			View.CanResend = App.HasSavedLastMessage;

			base.UpdateToView ();
		}

		protected override void OnViewLoaded ()
		{
			LoadTransientState ();
			base.OnViewLoaded ();
		}

		/// <summary>
		/// Fires every time the View is Shown.
		/// Base impl refreshes view data if that hasn't occurred yet.
		/// Call base impl as the last step.
		/// </summary>
		protected override void OnViewShown ()
		{
			if (!App.Settings.UserApprovedLocationServices)
			{
				if (!View.DisplayYesNoChoice ("This application accesses your location, press Ok to confirm or Cancel to exit.", "Confirm"))
				{
					AppServiceLocator.Instance.GetImpl<IAppHelper> ().ForceExit ();
					return;
				}
				App.Settings.UserApprovedLocationServices = true;
				App.SaveSettings ();
			}

			if (!m_AskedToRate && App.Settings.AskToRate && App.Settings.NumRuns % ASK_TO_RATE_NUM_INTERVAL == 0)
			{
				m_AskedToRate = true;

				OnUserAskedToRate ();
				if (View.DisplayYesNoChoice ("You've used this app {0} times, would you like to rate it?".FormatWith (App.Settings.NumRuns), "Rate me?"))
				{
					OnUserDecidedToRate ();
					App.Settings.AskToRate = false;
					App.SaveSettings ();
					App.LaunchMarketplaceAppDetails ();
					return;
				}
				
				if (View.DisplayYesNoChoice ("Do you want me to stop asking?", "Stop bugging me"))
				{
					OnUserWantsToStopRemindingToRate ();
					App.Settings.AskToRate = false;
					App.SaveSettings ();
				}
				else
				{
					OnUserWantsToKeepRemindingToRate ();
				}
			}

			base.OnViewShown ();
		}

		protected virtual void OnUserAskedToRate ()
		{
			// does nothing, method used for analytics
		}

		protected virtual void OnUserDecidedToRate ()
		{
			// does nothing, method used for analytics
		}

		protected virtual void OnUserWantsToStopRemindingToRate ()
		{
			// does nothing, method used for analytics
		}

		protected virtual void OnUserWantsToKeepRemindingToRate ()
		{
			// does nothing, method used for analytics
		}
		#endregion

		#region AbstractAppPresenter implementation
		protected override void DoAppSuspendingWork ()
		{
			base.DoAppSuspendingWork ();
			SaveTransientState ();
		}
		#endregion

		#region Event handlers
		private void OnDoSelectContacts ()
		{
			View.EnableAllControls (false);
			SaveTransientState ();
			ExecuteAsync (() => new SelectContactsPresenter ().Show ());
		}

		private void OnDoResend ()
		{
			SaveTransientState ();
			App.SendLastMessage ();
		}

		private void OnDoOpenAboutView ()
		{
			View.EnableAllControls (false);
			SaveTransientState ();
			ExecuteAsync (() => new AboutPresenter ().Show ());
		}

		private void OnDoLaunchAppRateLink ()
		{
			View.EnableAllControls (false);
			SaveTransientState ();
			AppServiceLocator.Instance.GetImpl<ILaunchMarketplaceAppDetailsService> ().Launch ();
		}

		private void OnDoOpenSettingsView ()
		{
			View.EnableAllControls (false);
			SaveTransientState ();
			ExecuteAsync (() => new SettingsPresenter ().Show ());
		}
		#endregion

		#region helpers
		private void SaveTransientState ()
		{
			m_TransientState[ASKED_TO_RATE] = m_AskedToRate;
		}

		private void LoadTransientState ()
		{
			if (m_TransientState.ContainsKey (ASKED_TO_RATE))
			{
				var asked = m_TransientState[ASKED_TO_RATE] as bool?;
				if (asked.HasValue)
					m_AskedToRate = asked.Value;
			}
		}

		private void ClearTransientState ()
		{
			if (m_TransientState.ContainsKey (ASKED_TO_RATE))
			{
				m_TransientState[ASKED_TO_RATE] = null;
				m_TransientState.Remove (ASKED_TO_RATE);
			}
		}
		#endregion
	}
}
